<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Timer.5 - Synchronising completion handlers in multithreaded programs</title>
<link rel="stylesheet" href="../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../../boost_asio.html" title="Boost.Asio">
<link rel="up" href="../tutorial.html" title="Tutorial">
<link rel="prev" href="tuttimer4/src.html" title="Source listing for Timer.4">
<link rel="next" href="tuttimer5/src.html" title="Source listing for Timer.5">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../boost.png"></td>
<td align="center"><a href="../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="tuttimer4/src.html"><img src="../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../tutorial.html"><img src="../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../boost_asio.html"><img src="../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="tuttimer5/src.html"><img src="../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="boost_asio.tutorial.tuttimer5"></a><a class="link" href="tuttimer5.html" title="Timer.5 - Synchronising completion handlers in multithreaded programs">Timer.5 - Synchronising
      completion handlers in multithreaded programs</a>
</h3></div></div></div>
<p>
        This tutorial demonstrates the use of the <a class="link" href="../reference/strand.html" title="strand">strand</a>
        class template to synchronise completion handlers in a multithreaded program.
      </p>
<p>
        The previous four tutorials avoided the issue of handler synchronisation
        by calling the boost::asio::io_context::run() function from one thread only.
        As you already know, the asio library provides a guarantee that completion
        handlers will only be called from threads that are currently calling boost::asio::io_context::run().
        Consequently, calling boost::asio::io_context::run() from only one thread
        ensures that completion handlers cannot run concurrently.
      </p>
<p>
        The single threaded approach is usually the best place to start when developing
        applications using asio. The downside is the limitations it places on programs,
        particularly servers, including:
      </p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
            Poor responsiveness when handlers can take a long time to complete.
          </li>
<li class="listitem">
            An inability to scale on multiprocessor systems.
          </li>
</ul></div>
<p>
        If you find yourself running into these limitations, an alternative approach
        is to have a pool of threads calling boost::asio::io_context::run(). However,
        as this allows handlers to execute concurrently, we need a method of synchronisation
        when handlers might be accessing a shared, thread-unsafe resource.
      </p>
<pre class="programlisting"><span class="special">#</span><span class="identifier">include</span> <span class="special">&lt;</span><span class="identifier">functional</span><span class="special">&gt;</span>
<span class="special">#</span><span class="identifier">include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</span>
<span class="special">#</span><span class="identifier">include</span> <span class="special">&lt;</span><span class="identifier">thread</span><span class="special">&gt;</span>
<span class="special">#</span><span class="identifier">include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">asio</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
</pre>
<p>
        We start by defining a class called <code class="computeroutput"><span class="identifier">printer</span></code>,
        similar to the class in the previous tutorial. This class will extend the
        previous tutorial by running two timers in parallel.
      </p>
<pre class="programlisting"><span class="keyword">class</span> <span class="identifier">printer</span>
<span class="special">{</span>
<span class="keyword">public</span><span class="special">:</span>
</pre>
<p>
        In addition to initialising a pair of boost::asio::steady_timer members,
        the constructor initialises the <code class="computeroutput"><span class="identifier">strand_</span></code>
        member, an object of type boost::asio::strand&lt;boost::asio::io_context::executor_type&gt;.
      </p>
<p>
        The <a class="link" href="../reference/strand.html" title="strand">strand</a> class template
        is an executor adapter that guarantees that, for those handlers that are
        dispatched through it, an executing handler will be allowed to complete before
        the next one is started. This is guaranteed irrespective of the number of
        threads that are calling boost::asio::io_context::run(). Of course, the handlers
        may still execute concurrently with other handlers that were not dispatched
        through an <a class="link" href="../reference/strand.html" title="strand">strand</a>, or
        were dispatched through a different <a class="link" href="../reference/strand.html" title="strand">strand</a>
        object.
      </p>
<pre class="programlisting">  <span class="identifier">printer</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">asio</span><span class="special">::</span><span class="identifier">io_context</span><span class="special">&amp;</span> <span class="identifier">io</span><span class="special">)</span>
    <span class="special">:</span> <span class="identifier">strand_</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">asio</span><span class="special">::</span><span class="identifier">make_strand</span><span class="special">(</span><span class="identifier">io</span><span class="special">)),</span>
      <span class="identifier">timer1_</span><span class="special">(</span><span class="identifier">io</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">asio</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">seconds</span><span class="special">(</span><span class="number">1</span><span class="special">)),</span>
      <span class="identifier">timer2_</span><span class="special">(</span><span class="identifier">io</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">asio</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">seconds</span><span class="special">(</span><span class="number">1</span><span class="special">)),</span>
      <span class="identifier">count_</span><span class="special">(</span><span class="number">0</span><span class="special">)</span>
  <span class="special">{</span>
</pre>
<p>
        When initiating the asynchronous operations, each completion handler is "bound"
        to an boost::asio::strand&lt;boost::asio::io_context::executor_type&gt; object.
        The boost::asio::bind_executor() function returns a new handler that automatically
        dispatches its contained handler through the <a class="link" href="../reference/strand.html" title="strand">strand</a>
        object. By binding the handlers to the same <a class="link" href="../reference/strand.html" title="strand">strand</a>,
        we are ensuring that they cannot execute concurrently.
      </p>
<pre class="programlisting">    <span class="identifier">timer1_</span><span class="special">.</span><span class="identifier">async_wait</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">asio</span><span class="special">::</span><span class="identifier">bind_executor</span><span class="special">(</span><span class="identifier">strand_</span><span class="special">,</span>
          <span class="identifier">std</span><span class="special">::</span><span class="identifier">bind</span><span class="special">(&amp;</span><span class="identifier">printer</span><span class="special">::</span><span class="identifier">print1</span><span class="special">,</span> <span class="keyword">this</span><span class="special">)));</span>

    <span class="identifier">timer2_</span><span class="special">.</span><span class="identifier">async_wait</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">asio</span><span class="special">::</span><span class="identifier">bind_executor</span><span class="special">(</span><span class="identifier">strand_</span><span class="special">,</span>
          <span class="identifier">std</span><span class="special">::</span><span class="identifier">bind</span><span class="special">(&amp;</span><span class="identifier">printer</span><span class="special">::</span><span class="identifier">print2</span><span class="special">,</span> <span class="keyword">this</span><span class="special">)));</span>
  <span class="special">}</span>

  <span class="special">~</span><span class="identifier">printer</span><span class="special">()</span>
  <span class="special">{</span>
    <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="string">"Final count is "</span> <span class="special">&lt;&lt;</span> <span class="identifier">count_</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
  <span class="special">}</span>
</pre>
<p>
        In a multithreaded program, the handlers for asynchronous operations should
        be synchronised if they access shared resources. In this tutorial, the shared
        resources used by the handlers (<code class="computeroutput"><span class="identifier">print1</span></code>
        and <code class="computeroutput"><span class="identifier">print2</span></code>) are <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span></code>
        and the <code class="computeroutput"><span class="identifier">count_</span></code> data member.
      </p>
<pre class="programlisting">  <span class="keyword">void</span> <span class="identifier">print1</span><span class="special">()</span>
  <span class="special">{</span>
    <span class="keyword">if</span> <span class="special">(</span><span class="identifier">count_</span> <span class="special">&lt;</span> <span class="number">10</span><span class="special">)</span>
    <span class="special">{</span>
      <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="string">"Timer 1: "</span> <span class="special">&lt;&lt;</span> <span class="identifier">count_</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
      <span class="special">++</span><span class="identifier">count_</span><span class="special">;</span>

      <span class="identifier">timer1_</span><span class="special">.</span><span class="identifier">expires_at</span><span class="special">(</span><span class="identifier">timer1_</span><span class="special">.</span><span class="identifier">expiry</span><span class="special">()</span> <span class="special">+</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">asio</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">seconds</span><span class="special">(</span><span class="number">1</span><span class="special">));</span>

      <span class="identifier">timer1_</span><span class="special">.</span><span class="identifier">async_wait</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">asio</span><span class="special">::</span><span class="identifier">bind_executor</span><span class="special">(</span><span class="identifier">strand_</span><span class="special">,</span>
            <span class="identifier">std</span><span class="special">::</span><span class="identifier">bind</span><span class="special">(&amp;</span><span class="identifier">printer</span><span class="special">::</span><span class="identifier">print1</span><span class="special">,</span> <span class="keyword">this</span><span class="special">)));</span>
    <span class="special">}</span>
  <span class="special">}</span>

  <span class="keyword">void</span> <span class="identifier">print2</span><span class="special">()</span>
  <span class="special">{</span>
    <span class="keyword">if</span> <span class="special">(</span><span class="identifier">count_</span> <span class="special">&lt;</span> <span class="number">10</span><span class="special">)</span>
    <span class="special">{</span>
      <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="string">"Timer 2: "</span> <span class="special">&lt;&lt;</span> <span class="identifier">count_</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
      <span class="special">++</span><span class="identifier">count_</span><span class="special">;</span>

      <span class="identifier">timer2_</span><span class="special">.</span><span class="identifier">expires_at</span><span class="special">(</span><span class="identifier">timer2_</span><span class="special">.</span><span class="identifier">expiry</span><span class="special">()</span> <span class="special">+</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">asio</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">seconds</span><span class="special">(</span><span class="number">1</span><span class="special">));</span>

      <span class="identifier">timer2_</span><span class="special">.</span><span class="identifier">async_wait</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">asio</span><span class="special">::</span><span class="identifier">bind_executor</span><span class="special">(</span><span class="identifier">strand_</span><span class="special">,</span>
            <span class="identifier">std</span><span class="special">::</span><span class="identifier">bind</span><span class="special">(&amp;</span><span class="identifier">printer</span><span class="special">::</span><span class="identifier">print2</span><span class="special">,</span> <span class="keyword">this</span><span class="special">)));</span>
    <span class="special">}</span>
  <span class="special">}</span>

<span class="keyword">private</span><span class="special">:</span>
  <span class="identifier">boost</span><span class="special">::</span><span class="identifier">asio</span><span class="special">::</span><span class="identifier">strand</span><span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">asio</span><span class="special">::</span><span class="identifier">io_context</span><span class="special">::</span><span class="identifier">executor_type</span><span class="special">&gt;</span> <span class="identifier">strand_</span><span class="special">;</span>
  <span class="identifier">boost</span><span class="special">::</span><span class="identifier">asio</span><span class="special">::</span><span class="identifier">steady_timer</span> <span class="identifier">timer1_</span><span class="special">;</span>
  <span class="identifier">boost</span><span class="special">::</span><span class="identifier">asio</span><span class="special">::</span><span class="identifier">steady_timer</span> <span class="identifier">timer2_</span><span class="special">;</span>
  <span class="keyword">int</span> <span class="identifier">count_</span><span class="special">;</span>
<span class="special">};</span>
</pre>
<p>
        The <code class="computeroutput"><span class="identifier">main</span></code> function now causes
        boost::asio::io_context::run() to be called from two threads: the main thread
        and one additional thread. This is accomplished using an boost::thread object.
      </p>
<p>
        Just as it would with a call from a single thread, concurrent calls to boost::asio::io_context::run()
        will continue to execute while there is "work" left to do. The
        background thread will not exit until all asynchronous operations have completed.
      </p>
<pre class="programlisting"><span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span>
<span class="special">{</span>
  <span class="identifier">boost</span><span class="special">::</span><span class="identifier">asio</span><span class="special">::</span><span class="identifier">io_context</span> <span class="identifier">io</span><span class="special">;</span>
  <span class="identifier">printer</span> <span class="identifier">p</span><span class="special">(</span><span class="identifier">io</span><span class="special">);</span>
  <span class="identifier">std</span><span class="special">::</span><span class="identifier">thread</span> <span class="identifier">t</span><span class="special">([&amp;]{</span> <span class="identifier">io</span><span class="special">.</span><span class="identifier">run</span><span class="special">();</span> <span class="special">});</span>
  <span class="identifier">io</span><span class="special">.</span><span class="identifier">run</span><span class="special">();</span>
  <span class="identifier">t</span><span class="special">.</span><span class="identifier">join</span><span class="special">();</span>

  <span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="special">}</span>
</pre>
<p>
        See the <a class="link" href="tuttimer5/src.html" title="Source listing for Timer.5">full source listing</a>
      </p>
<p>
        Return to the <a class="link" href="../tutorial.html" title="Tutorial">tutorial index</a>
      </p>
<p>
        Previous: <a class="link" href="tuttimer4.html" title="Timer.4 - Using a member function as a completion handler">Timer.4 - Using a
        member function as a completion handler</a>
      </p>
</div>
<div class="copyright-footer">Copyright © 2003-2025 Christopher M.
      Kohlhoff<p>
        Distributed under the Boost Software License, Version 1.0. (See accompanying
        file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
      </p>
</div>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="tuttimer4/src.html"><img src="../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../tutorial.html"><img src="../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../boost_asio.html"><img src="../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="tuttimer5/src.html"><img src="../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>
